/*************使用说明*************
2024/1/13：满荣编辑
1.需要在library中搜索并安装ModbusRTUSlave,作者为by C. M. Bulliner
2.根据需要使用软件串口还是硬件串口，如果使用RS485，注意是否需要使能引脚。
3.在主程序的初始化函数中调用void ModbusRTUInitialize(int address, uint32_t rate, byte config)方法，传入地址号和波特率,config可不写，不写则使用默认参数8N1
4.将DoModbusRTU()方法放在循环函数中不停调用。
*/

#ifndef _myModbus_H_
#define _myModbus_H_

#include <Arduino.h>
#include <ModbusRTUSlave.h>


const uint8_t dePin = 17; //RS485使能引脚


//#define CoilCount 10       // 输出线圈数量
//#define DiscreteCount 10   // 离散输入数量
#define HoldingRegCount 40 // 保持寄存器数量
//#define InputRegCount 10   // 输入寄存器数量


/****************************以下为程序开始，尽量别修改**************************************/
/*
使用硬件串口初始化，
Serial0:RX0 44  TX0 43
Serial1:RX1 15  TX1 16  
Serial2:RX2 19  TX2 20
*/
ModbusRTUSlave modbus(Serial1, dePin); // serial port, driver enable pin for rs-485 (optional)


// 判断是否声明输出线圈
#if defined(CoilCount) && (CoilCount > 0)
#define EnableCoil ;
bool coils[CoilCount]; // 输出线圈
#endif
// 判断是否声明输入线圈
#if defined(DiscreteCount) && (DiscreteCount > 0)
#define EnanleDiscrete
bool discreteInputs[DiscreteCount]; // 离散输入
#endif
// 判断是否声明保持寄存器
#if defined(HoldingRegCount) && (HoldingRegCount > 0)
#define EnableHoldingReg
uint16_t holdingRegisters[HoldingRegCount]; // 保持寄存器
#endif
// 判断是否声明输入寄存器
#if defined(InputRegCount) && (InputRegCount > 0)
#define EnableInputReg
uint16_t inputRegisters[InputRegCount]; // 输入寄存器
#endif

/// 声明一个执行了Modbus的循环回调函数
void (*MbsCallback)();

/// @brief 放在轮询函数中
void DoModbusRTU()
{    
    modbus.poll();
    if (MbsCallback != NULL)
    {
        MbsCallback();
    }
}

/// @brief Modbus初始化
/// @param address 从站地址
/// @param rate 波特率
/// @param config 通信参数，默认8N1,可以使用SERIAL_8E1 SERIAL_8O1 SERIAL_8N2 SERIAL_8E2 SERIAL_8O2等待
void ModbusRTUInitialize(int address, uint32_t rate)
{
#ifdef EnableCoil
    modbus.configureCoils(coils, sizeof(coils) / sizeof(bool)); // bool array of coil values, number of coils
#endif
#ifdef EnanleDiscrete
    modbus.configureDiscreteInputs(discreteInputs, sizeof(discreteInputs) / sizeof(bool)); // bool array of discrete input values, number of discrete inputs
#endif
#ifdef EnableHoldingReg
    modbus.configureHoldingRegisters(holdingRegisters, sizeof(holdingRegisters) / sizeof(uint16_t)); // unsigned 16 bit integer array of holding register values, number of holding registers
#endif
#ifdef EnableInputReg
    modbus.configureInputRegisters(inputRegisters, sizeof(inputRegisters) / sizeof(uint16_t)); // unsigned 16 bit integer array of input register values, number of input registers
#endif
    modbus.begin(address, rate); // slave id, baud rate, config (optional)
}

#endif
